package org.activequant.dao.hibernate.types;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;

/**
 * Hibernate helper to convert simple types to/from SQL type.
 * <br/>
 * An abstract class. SimpleType implements UserType.<br/>
 * Holds the following associated variable:
 * <ul>
 * <li>sqlTypes(int[])</li>
 * </ul>
 * Defines the following abstract methods:
 * <ul>
 * <li>Object parse(String val)</li>
 * <li>String format(Object obj)</li>
 * </ul>
 * <b>History:</b><br>
 *  - [Nov 6, 2007] Created (Mike Kroutikov)<br>
 *  - [07.11.2007] Minor fixes (Erik Nijkamp)<br>
 *
 *  @author Mike Kroutikov
 */
public abstract class SimpleType implements UserType {	
	/**
	 * private final static int[] sqlTypes = new int[] { Types.VARCHAR };
	 */
	private final static int[] sqlTypes = new int[] { Types.VARCHAR };
	/**
	 * An abstract method, returns an Object by parsing the given val(String)
	 * @param val
	 * @return
	 */
	protected abstract Object parse(String val);
	/**
	 * An abstract method, returns a String by formatting the given obj(Object)
	 * @param obj
	 * @return
	 */
	protected abstract String format(Object obj);
	/**
	 * returns the given state(Serializable)
	 */
	public Object assemble(Serializable state, Object owner) throws HibernateException {
		return state;
	}
	/**
	 * returns the given obj(Object)
	 */
	public Object deepCopy(Object obj) throws HibernateException {
		return obj;
	}
	/**
	 * returns the given value(Object) as Serializable (cast)
	 */
	public Serializable disassemble(Object value) throws HibernateException {
		return (Serializable) value;
	}
	
	public boolean equals(Object x, Object y) throws HibernateException {
		if(x == y) return true;
		return (x != null && y != null && x.equals(y));
	}
	/**
	 * returns <code>value.hashCode()</code> of the given value(Object)
	 */
	public int hashCode(Object value) throws HibernateException {
		return value.hashCode();
	}
	/**
	 * returns false
	 */
	public boolean isMutable() {
		return false;
	}
	/**
	 * <strong>1.</strong> Gets the str(String) found in the given names[0](String) column in the given rs(ResultSet)<br/>
	 * <strong>2.</strong> Return an Object by parsing that str(String) (using the abstract <code>parse(String val)</code> method)
	 */
	public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
		String str = rs.getString(names[0]);
		return str == null ? null : parse(str);
	}
	/**
	 * <strong>1.</strong> If the given value(Object) is not null, it will format it to a String and set it in the given st(PreparedStatement) at the 
	 * given index(int) position.<br/>
	 * <strong>2.</strong> Otherwise sets a NULL VARCHAR in the given st(PreparedStatement) at the given index(int) position.
	 */
	public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
		if(value != null) {
			st.setString(index, format(value));
		} else {
			st.setNull(index, Types.VARCHAR);
		}
	}
	/**
	 * returns the given original(Object)
	 */
	public Object replace(Object original, Object targete, Object owner) throws HibernateException {
		return original;
	}
	/**
	 * returns the associated sqlTypes(int[]) (new int[]{Types.VARCHAR})
	 */
	public int[] sqlTypes() {
		return sqlTypes;
	}
}
